package com.atguigu.tingshu.album.service.impl;

import cn.hutool.core.date.DateUtil;
import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.AlbumStatMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.AuthContextHolder;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.AlbumStat;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.model.user.UserInfo;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.cos.utils.DateUtils;
import com.qcloud.vod.VodUploadClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@Service
@Transactional
@SuppressWarnings({"unchecked", "rawtypes"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

    @Autowired
    private TrackInfoMapper trackInfoMapper;

    @Autowired
    private TrackStatMapper trackStatMapper;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

    @Autowired
    private VodService vodService;

    @Autowired
    private UserInfoFeignClient userInfoFeignClient;

    @Autowired
    private AlbumStatMapper albumStatMapper;

    @Override
    public UploadTrackVo uploadTrack(MultipartFile file) {
        return vodService.uploadTrack(file);
    }

    @Override
    public void saveTrackInfo(TrackInfoVo trackInfoVo) {

        //获取当前登录用户的id
        Long userId = AuthContextHolder.getUserId();
        TrackInfo trackInfo = new TrackInfo();
        // 设置声音信息
        BeanUtils.copyProperties(trackInfoVo, trackInfo);
        trackInfo.setSource(SystemConstant.TRACK_SOURCE_UPLOAD);
        trackInfo.setStatus(SystemConstant.TRACK_STATUS_PASS);
        trackInfo.setUserId(userId);

        //设置声音的排序值
        //查询当前用户下声音的最大排序值
        LambdaQueryWrapper<TrackInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TrackInfo::getAlbumId, trackInfoVo.getAlbumId())
                .orderByDesc(TrackInfo::getOrderNum)
                // 只查询一条
                .last("limit 1");
        TrackInfo dbTrackInfo = trackInfoMapper.selectOne(queryWrapper);
        if (dbTrackInfo == null) {
            trackInfo.setOrderNum(1);
        } else {
            trackInfo.setOrderNum(dbTrackInfo.getOrderNum() + 1);
        }


        //根据媒体文件id从腾讯云中获取
        String mediaFileId = trackInfoVo.getMediaFileId();

        TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(mediaFileId);
        //保存媒体文件数据
        trackInfo.setMediaDuration(new BigDecimal(trackMediaInfoVo.getDuration()));
        trackInfo.setMediaFileId(mediaFileId);
        trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
        trackInfo.setMediaSize(trackMediaInfoVo.getSize());
        trackInfo.setMediaType(trackMediaInfoVo.getType());
        trackInfoMapper.insert(trackInfo);

        //2.初始化声音的统计数据

        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
        this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);

        //3.修改albume_info表中的数据
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
        // 专辑声音数量
        Integer includeTrackCount = albumInfo.getIncludeTrackCount();
        albumInfo.setIncludeTrackCount(includeTrackCount + 1);
        albumInfoMapper.updateById(albumInfo);


    }

    //分页查询
    @Override
    public IPage<TrackListVo> findUserTrackPage(Long page, Long limit, TrackInfoQuery trackInfoQuery) {
        Page<TrackListVo> result = new Page<>(page, limit);
        return trackInfoMapper.findUserTrackPage(result, trackInfoQuery);
    }

    //    根据id查询声音信息
    @Override
    public TrackInfo getTrackInfoById(Long id) {
        Long userId = AuthContextHolder.getUserId();
        TrackInfo trackInfo = trackInfoMapper.selectById(id);
        trackInfo.setUserId(userId);
        return trackInfo;
    }

    // 修改声音信息
    @Override
    public void updateTrackInfo(Long id, TrackInfoVo trackInfoVo) {
        //根据id先查询声音原数据
        TrackInfo trackInfo = trackInfoMapper.selectById(id);
        String mediaFileId = trackInfoVo.getMediaFileId();
        String dbMediaFileId = trackInfo.getMediaFileId();
        BeanUtils.copyProperties(trackInfoVo, trackInfo);

        if (!mediaFileId.equals(dbMediaFileId)) {
            TrackMediaInfoVo mediaInfo = vodService.getMediaInfo(mediaFileId);
            trackInfo.setMediaSize(mediaInfo.getSize());
            trackInfo.setMediaType(mediaInfo.getType());
            trackInfo.setMediaUrl(mediaInfo.getMediaUrl());
            trackInfo.setMediaDuration(new BigDecimal(mediaInfo.getDuration()));
        }
        trackInfoMapper.updateById(trackInfo);

    }

    //根据id删除声音信息
    @Override
    public void deleteTrackInfo(Long id) {

        //根据id先查询声音原数据
        TrackInfo trackInfo = trackInfoMapper.selectById(id);
        //根据id删除声音原数据
        trackInfoMapper.deleteById(id);
        //2、根据声音的id删除声音的统计数据
        LambdaQueryWrapper<TrackStat> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TrackStat::getTrackId, id);
        trackStatMapper.delete(queryWrapper);

        // 3、修改album_info表中的数据(include_track_count)
        Long albumId = trackInfo.getAlbumId();
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        Integer includeTrackCount = albumInfo.getIncludeTrackCount();
        albumInfo.setIncludeTrackCount(includeTrackCount - 1);
        albumInfoMapper.updateById(albumInfo);

        // 4、删除云点播服务中的媒体数据
        vodService.deleteMedia(trackInfo.getMediaFileId());
    }


    //获取专辑声音分页列表
    @Override
    public IPage<AlbumTrackListVo> findAlbumTrackPage(Long albumId, Long limit, Long page) {

        Page<AlbumTrackListVo> page1 = new Page<>(page, limit);
        IPage<AlbumTrackListVo> pageInfo = trackInfoMapper.selectPageByAlbumId(albumId, page1);


        //获取当前页的声音列表
        List<AlbumTrackListVo> records = pageInfo.getRecords();


        //根据album获取albumInfo
        AlbumInfo albumInfo = albumInfoMapper.selectById(albumId);
        //判断用户是否登录
        Long userId = AuthContextHolder.getUserId();
        if (userId == null) {
            //如果是非免费的,那么只能试听5集,除了试听集数外,其他集数显示付费表示
            if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
                records.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
                        .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
            }
        } else {   //已登录
            //获取付费类型
            String payType = albumInfo.getPayType();

            //是否是vip免费
            if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(payType)) {
                //远程调用,获取当前登录用户的信息数据
                Result<UserInfo> userInfoResult = userInfoFeignClient.getUserInfoById(userId);
                UserInfo userInfo = userInfoResult.getData();

                //判断当前用户是不是vip用户   0代表不是vip用户 ,1代表是vip用户
                if (userInfo.getIsVip() == 0) {

                    records.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
                            .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
                } else {
                    //当前用户是vip用户,校验用户的vip是否过期
                    //获取vip过期时间

                    //如果现在的时间大于vip过期的时间,说明用户vip已经过期
                    if (new Date().after(userInfo.getVipExpireTime())) {
                        records.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
                                .forEach(albumTrackListVo -> albumTrackListVo.setIsShowPaidMark(true));
                    }

                }
            }

            //付费专辑
            else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(payType)) {
                //判断当前用户是否购买过专辑和声音
                List<Long> trackIds = records.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
                        .map(albumTrackListVo -> albumTrackListVo.getTrackId()).collect(Collectors.toList());

                Result<Map<Long, Integer>> mapResult = userInfoFeignClient.userIsPaidAlbumAndTrack(albumId, trackIds);

                // 构建records中的每一个声音的isShowPaidMark字段的值
                Map<Long, Integer> map = mapResult.getData();
                records.stream().filter(albumTrackListVo -> albumTrackListVo.getOrderNum() > albumInfo.getTracksForFree())
                        .forEach(albumTrackListVo -> {
                            //根据当前页中的id在map中查看是否购买过,如果购买过,则为0,不显示,如果没购买过则显示
                            Long trackId = albumTrackListVo.getTrackId();
                            Integer id = map.get(trackId);
                            Boolean isShowPaidMark = id == 0;
                            albumTrackListVo.setIsShowPaidMark(isShowPaidMark);
                        });
            }


        }


        return pageInfo;
    }

    @Override
    public void trackStatUpdate(TrackStatMqVo trackStatMqVo) {
        // 更新声音播放量记录
        LambdaQueryWrapper<TrackStat> trackStatLambdaQueryWrapper = new LambdaQueryWrapper<>();
        trackStatLambdaQueryWrapper.eq(TrackStat::getTrackId, trackStatMqVo.getTrackId())
                .eq(TrackStat::getStatType, trackStatMqVo.getStatType());
        TrackStat trackStat = trackStatMapper.selectOne(trackStatLambdaQueryWrapper);
        trackStat.setStatNum(trackStat.getStatNum() + trackStatMqVo.getCount());
        trackStatMapper.update(trackStat, trackStatLambdaQueryWrapper);

        //更新专辑播放量记录
        LambdaQueryWrapper<AlbumStat> albumStatLambdaQueryWrapper = new LambdaQueryWrapper<>();
        albumStatLambdaQueryWrapper.eq(AlbumStat::getAlbumId, trackStatMqVo.getAlbumId())
                .eq(AlbumStat::getStatType, trackStatMqVo.getStatType());
        AlbumStat albumStat = albumStatMapper.selectOne(albumStatLambdaQueryWrapper);
        albumStat.setStatNum(albumStat.getStatNum() + trackStatMqVo.getCount());
        albumStatMapper.update(albumStat, albumStatLambdaQueryWrapper);

    }


    //获取声音统计信息
    @Override
    public TrackStatVo getTrackStatVo(Long trackId) {
        TrackStatVo trackStatVo = trackStatMapper.getTrackStatVo(trackId);
        return trackStatVo;
    }


    //获取用户声音分集购买支付列表
    @Override
    public List<TrackPayVo> findUserTrackPaidList(Long trackId) {

        //获取当前声音的信息和专辑的信息
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);
        AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfo.getAlbumId());


        // 查询当前登录用户购买的声音列表
        Long userId = AuthContextHolder.getUserId();

        //远程调用:获取用户购买过的声音id列表
        Result<List<Long>> listResult = userInfoFeignClient.findUserPaidTrackList(trackInfo.getAlbumId());
        List<Long> trackIds = listResult.getData();

        // 查询当前专辑声音的orderNum大于当前用户点击的声音的声音列表
        LambdaQueryWrapper<TrackInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(TrackInfo::getAlbumId, trackInfo.getAlbumId());
        lambdaQueryWrapper.gt(TrackInfo::getOrderNum, trackInfo.getOrderNum());
        lambdaQueryWrapper.orderByAsc(TrackInfo::getOrderNum);
        lambdaQueryWrapper.select(TrackInfo::getId);     //指定查询列
        List<TrackInfo> trackInfoList = trackInfoMapper.selectList(lambdaQueryWrapper);
        List<Long> trackIdList = trackInfoList.stream().map(trackInfo1 -> trackInfo1.getId()).collect(Collectors.toList());

        // 从第四步到的的声音集合中排除购买过的声音，得到未购买过的声音的列表
        //剩下的这些声音id就是用户点击的这个声音以及这个声音后面的所有未购买的声音
        List<Long> ids = new ArrayList<>();
        //如果用户未购买过任何声音
        if (CollectionUtils.isEmpty(trackIds)) {
            ids = trackIdList;
        } else {
            // 存在购买过的声音
            ids = trackIdList.stream().filter(id -> trackIds.contains(id)).collect(Collectors.toList());
        }
        // 第五步得到的声音列表为准构建声音购买分集列表
        List<TrackPayVo> trackPayVos = new ArrayList<>();

        //本集
        TrackPayVo trackPayVo = new TrackPayVo();
        trackPayVo.setName("本集");
        trackPayVo.setPrice(albumInfo.getPrice());
        trackPayVo.setTrackCount(0);
        trackPayVos.add(trackPayVo);

        // 以10集为一个单位构建分集列表
        int size = ids.size();
        if (size > 0 && size <= 10) {
            TrackPayVo trackPayVoAfterCount  = new TrackPayVo();
            trackPayVoAfterCount .setName("后" + size + "集");
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(size)).multiply(new BigDecimal("10"))
                    .divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
            trackPayVoAfterCount .setPrice(price);
            trackPayVoAfterCount.setTrackCount(size);
            trackPayVos.add(trackPayVoAfterCount);
        }

        if(size > 10) {
            TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
            trackPayVoAfterCount.setName("后10集" );
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(10)).multiply(new BigDecimal("10"))
                    .divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
            trackPayVoAfterCount.setPrice(price);
            trackPayVoAfterCount.setTrackCount(10);
            trackPayVos.add(trackPayVoAfterCount) ;
        }

        // 大于10
        if(size > 10 && size <= 20) {
            TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
            trackPayVoAfterCount.setName("后" + size + "集" );
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(size)).multiply(new BigDecimal("10"))
                    .divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
            trackPayVoAfterCount.setPrice(price);
            trackPayVoAfterCount.setTrackCount(size);
            trackPayVos.add(trackPayVoAfterCount) ;
        }
        // 大于20
        if (size > 20) {
            TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
            trackPayVoAfterCount.setName("后20集" );
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(20)).multiply(new BigDecimal("10"))
                    .divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
            trackPayVoAfterCount.setPrice(price);
            trackPayVoAfterCount.setTrackCount(20);
            trackPayVos.add(trackPayVoAfterCount) ;
        }

        if(size > 20 && size <= 30) {
            TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
            trackPayVoAfterCount.setName("后" + size + "集" );
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(size)).multiply(new BigDecimal("10"))
                    .divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
            trackPayVoAfterCount.setPrice(price);
            trackPayVoAfterCount.setTrackCount(size);
            trackPayVos.add(trackPayVoAfterCount) ;
        }

        // 大于30
        if(size > 30) {
            TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
            trackPayVoAfterCount.setName("后30集" );
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(40)).multiply(new BigDecimal("10"))
                    .divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
            trackPayVoAfterCount.setPrice(price);
            trackPayVoAfterCount.setTrackCount(30);
            trackPayVos.add(trackPayVoAfterCount) ;
        }

        if(size > 30 && size <= 50) {
            TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
            trackPayVoAfterCount.setName("后" + size + "集" );
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(size)).multiply(new BigDecimal("10"))
                    .divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
            trackPayVoAfterCount.setPrice(price);
            trackPayVoAfterCount.setTrackCount(size);
            trackPayVos.add(trackPayVoAfterCount) ;
        }

        // 大于50
        if(size > 50) {
            TrackPayVo trackPayVoAfterCount = new TrackPayVo() ;
            trackPayVoAfterCount.setName("后50集" );
            BigDecimal price = albumInfo.getPrice().multiply(new BigDecimal(50)).multiply(new BigDecimal("10"))
                    .divide(new BigDecimal("10"), 2, BigDecimal.ROUND_HALF_UP);
            trackPayVoAfterCount.setPrice(price);
            trackPayVoAfterCount.setTrackCount(50);
            trackPayVos.add(trackPayVoAfterCount) ;
        }

        return trackPayVos;
    }

    @Override
    public List<TrackInfo> findPaidTrackInfoList(Long trackId, Integer trackCount) {
        // 创建一个List集合对象，用来存储查询的结果数据
        List<TrackInfo> trackInfoList = new ArrayList<>() ;

        // 根据声音的id查询声音数据
        TrackInfo trackInfo = trackInfoMapper.selectById(trackId);

        // 获取专辑的id
        Long albumId = trackInfo.getAlbumId();

        // 从track_info表中查询需要购买的声音列表(需要排除已经购买过的声音id)
        // select * from track_info where album_id = ? and order_num > ? and id not in(....) limit ?
        Result<List<Long>> userPaidTrackList = userInfoFeignClient.findUserPaidTrackList(albumId);
        List<Long> userPaidTrackIds = userPaidTrackList.getData();

        // 判断trackCount是否大于0
        if(trackCount > 0) {

            LambdaQueryWrapper<TrackInfo> lambdaQueryWrapper = new LambdaQueryWrapper<>() ;
            lambdaQueryWrapper.eq(TrackInfo::getAlbumId, albumId) ;
            lambdaQueryWrapper.gt(TrackInfo::getOrderNum , trackInfo.getOrderNum()) ;
            lambdaQueryWrapper.orderByAsc(TrackInfo::getOrderNum) ;
            if(!CollectionUtils.isEmpty(userPaidTrackIds)) {
                lambdaQueryWrapper.notIn(TrackInfo::getId, userPaidTrackIds) ;
            }
            lambdaQueryWrapper.last("limit " + trackCount) ;
            trackInfoList = trackInfoMapper.selectList(lambdaQueryWrapper);

        }else {		// 购买的是本集
            trackInfoList.add(trackInfo) ;
        }
        return trackInfoList;
    }


    public void saveTrackStat(Long trackId, String statType) {
        TrackStat trackStat = new TrackStat();
        trackStat.setStatType(statType);
        trackStat.setTrackId(trackId);
        trackStat.setStatNum(0);
        trackStatMapper.insert(trackStat);

    }
}
